package com.blobfish.fiction.common.base.interceptor;

import cn.hutool.core.util.StrUtil;
import com.blobfish.fiction.common.base.constant.CommonMessageEnum;
import com.blobfish.fiction.common.base.controller.BaseController;
import com.blobfish.fiction.common.base.exception.GlobalErrorException;
import com.blobfish.fiction.common.base.knowledge.DataDictKnowledge;
import com.blobfish.fiction.common.util.RSACoderUtil;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
import com.jfinal.kit.PropKit;
import com.jfinal.log.Log;
import com.jfinal.plugin.redis.Redis;

/**
 * 权限拦截器
 * @author huangbo
 */
public class AuthInterceptor implements Interceptor {
    private static final Log log = Log.getLog(AuthInterceptor.class);

    @Override
    public void intercept(Invocation invocation) {
        Controller controller = invocation.getController();
        String requestMethod = controller.getRequest().getMethod();
        String actionKey = invocation.getActionKey();
        // 验证是否为不需要权限验证的url
        boolean isAnonUrl = Redis.use("master").sismember(PropKit.get("cacheName.AUTH_ANON_URL"), actionKey);
        if (!isAnonUrl) {
            // 获取cookie中的签名
            String sign = controller.getCookie("sign", "");
            String userName = controller.getCookie("userName", "");
            if (StrUtil.isBlank(sign) || StrUtil.isBlank(userName)) {
                doLoginOut(controller, requestMethod);
                return;
            } else {
                // 获取redis中保存的加密字段
                String encodedDataStr = Redis.use("master").get("auth:" + userName + ":encodedData");
                if (StrUtil.isBlank(encodedDataStr)) {
                    controller.redirect("/login/gotoLoginPage");
                    return;
                }
                byte[] encodedData = RSACoderUtil.decryptBASE64(encodedDataStr);
                try {
                    boolean isHasLogin = RSACoderUtil.verify(encodedData, PropKit.get("publicKey"), sign);
                    if (isHasLogin) {
                        // 如果已登录，则延长cookie的时间
                        controller.setCookie("sign", sign, PropKit.getInt("loginSignMaxAgeInSeconds"), true);
                        controller.setCookie("userName", userName, PropKit.getInt("loginSignMaxAgeInSeconds"), true);
                    } else {
                        // 否则返回登录页
                        controller.redirect("/login/gotoLoginPage");
                        return;
                    }
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            }
        }
        invocation.invoke();
    }

    /**
     * 执行登出操作
     * @param controller 控制器
     * @param requestMethod 当前访问方式
     */
    private void doLoginOut(Controller controller, String requestMethod) {
        if (DataDictKnowledge.RequestMethodTypeEnum.GET.getDataCode().equals(requestMethod)) {
            // 如果是get请求的直接重定向到登录界面
            controller.redirect("/login/gotoLoginPage");
        } else if (DataDictKnowledge.RequestMethodTypeEnum.POST.getDataCode().equals(requestMethod)) {
            // 如果是post请求则直接抛出异常
            throw new GlobalErrorException(CommonMessageEnum.LOGON_FAILURE);
        }
    }
}
